package com.magic.kit;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

public final class DateKit {
	/**
	 * 英文简写（默认）如：2010-12-01
	 */
	public static String FORMAT_YEAR = "yyyy";
	public static String FORMAT_MONTH = "MM";
	/**
	 * 英文简写（默认）如：2010-12-01
	 */
	public static String FORMAT_SHORT = "yyyy-MM-dd";
	/**
	 * 英文全称 如：2010-12-01 23:15:06
	 */
	public static String FORMAT_LONG = "yyyy-MM-dd HH:mm:ss";
	/**
	 * 精确到毫秒的完整时间 如：yyyy-MM-dd HH:mm:ss.S
	 */
	public static String FORMAT_FULL = "yyyy-MM-dd HH:mm:ss.S";
	/**
	 * 中文简写 如：2010年12月01日
	 */
	public static String FORMAT_SHORT_CN = "yyyy年MM月dd";
	/**
	 * 中文全称 如：2010年12月01日 23时15分06秒
	 */
	public static String FORMAT_LONG_CN = "yyyy年MM月dd日  HH时mm分ss秒";
	/**
	 * 精确到毫秒的完整中文时间
	 */
	public static String FORMAT_FULL_CN = "yyyy年MM月dd日  HH时mm分ss秒SSS毫秒";

	/**
	 * 获得默认的 date pattern
	 */
	public static String getDatePattern() {
		return FORMAT_LONG;
	}

	/**
	 * 根据预设格式返回当前日期
	 * 
	 * @return 日期字符串
	 */
	public static String getNow() {
		return format(new Date());
	}

	/**
	 * 根据用户格式返回当前日期
	 * 
	 * @param format
	 *            格式化类型
	 * @return 日期字符串
	 */
	public static String getNow(String format) {
		return format(new Date(), format);
	}

	/**
	 * 使用预设格式格式化日期
	 * 
	 * @param date
	 *            日期
	 * @return 日期字符串
	 */
	public static String format(Date date) {
		return format(date, getDatePattern());
	}

	/**
	 * 使用用户格式格式化日期
	 * 
	 * @param date
	 *            日期
	 * @param pattern
	 *            日期格式
	 * @return 日期字符串
	 */
	public static String format(Date date, String pattern) {
		String returnValue = "";
		if (date != null) {
			SimpleDateFormat df = new SimpleDateFormat(pattern);
			returnValue = df.format(date);
		}
		return (returnValue);
	}

	/**
	 * 使用预设格式提取字符串日期
	 * 
	 * @param strDate
	 *            日期字符串
	 * @return 日期字符串
	 * @throws ParseException
	 */
	public static Date parse(String strDate) throws ParseException {
		return parse(strDate, getDatePattern());
	}

	/**
	 * 使用用户格式提取字符串日期
	 * 
	 * @param strDate
	 *            日期字符串
	 * @param pattern
	 *            日期格式
	 * @return 日期字符串
	 * @throws ParseException
	 */
	public static Date parse(String strDate, String pattern) throws ParseException {
		SimpleDateFormat df = new SimpleDateFormat(pattern);
		return df.parse(strDate);
	}

	/**
	 * 在日期上增加数个整月
	 * 
	 * @param date
	 *            日期
	 * @param n
	 *            要增加的月数
	 * @return 日期字符串
	 */
	public static Date addMonth(Date date, int n) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.MONTH, n);
		return cal.getTime();
	}

	/**
	 * 在日期上增加天数
	 * 
	 * @param date
	 *            日期
	 * @param n
	 *            要增加的天数
	 * @return 日期字符串
	 */
	public static Date addDay(Date date, int n) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.DATE, n);
		return cal.getTime();
	}

	/**
	 * 在小时上增加小时数
	 * 
	 * @param date
	 *            日期
	 * @param n
	 *            要增加的小时数
	 * @return 日期字符串
	 */
	public static Date addHours(Date date, int n) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.HOUR_OF_DAY, n);
		return cal.getTime();
	}

	/**
	 * 在分钟上增加小时数
	 * 
	 * @param date
	 *            日期
	 * @param n
	 *            要增加的小时数
	 * @return 日期字符串
	 */
	public static Date addMinutes(Date date, int n) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.MINUTE, n);
		return cal.getTime();
	}

	/**
	 * 获取时间戳
	 * 
	 * @return 日期字符串
	 */
	public static String getTimeString() {
		SimpleDateFormat df = new SimpleDateFormat(FORMAT_FULL);
		Calendar calendar = Calendar.getInstance();
		return df.format(calendar.getTime());
	}

	/**
	 * 获取日期年份
	 * 
	 * @param date
	 *            日期
	 * @return 日期字符串
	 */
	public static String getYear(Date date) {
		return format(date).substring(0, 4);
	}

	/**
	 * 按默认格式的字符串距离今天的天数
	 * 
	 * @param date
	 *            日期字符串
	 * @return 天数
	 * @throws ParseException
	 */
	public static int countDays(String date) throws ParseException {
		long t = Calendar.getInstance().getTime().getTime();
		Calendar c = Calendar.getInstance();
		c.setTime(parse(date));
		long t1 = c.getTime().getTime();
		return (int) (t / 1000 - t1 / 1000) / 3600 / 24;
	}

	/**
	 * 按默认格式的字符串距离今天的天数
	 * 
	 * @param date
	 *            日期字符串
	 * @return 天数
	 */
	public static int countDays(Date date) {
		long t = Calendar.getInstance().getTime().getTime();
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		long t1 = c.getTime().getTime();
		return (int) (t / 1000 - t1 / 1000) / 3600 / 24;
	}

	/**
	 * 按默认格式的字符串距离今天的小时数
	 * 
	 * @param date
	 *            日期字符串
	 * @return 天数
	 */
	public static int countHours(Date date) {
		long t = Calendar.getInstance().getTime().getTime();
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		long t1 = c.getTime().getTime();
		return (int) (t / 1000 - t1 / 1000) / 3600;
	}

	/**
	 * 按默认格式的字符串距离今天的分钟数
	 * 
	 * @param date
	 *            日期字符串
	 * @return 天数
	 */
	public static int countMinutes(Date date) {
		long t = Calendar.getInstance().getTime().getTime();
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		long t1 = c.getTime().getTime();
		return (int) (t / 1000 - t1 / 1000) / 60;
	}

	/**
	 * 按用户格式字符串距离今天的天数
	 * 
	 * @param date
	 *            日期字符串
	 * @param format
	 *            日期格式
	 * @return 天数
	 * @throws ParseException
	 */
	public static int countDays(String date, String format) throws ParseException {
		long t = Calendar.getInstance().getTime().getTime();
		Calendar c = Calendar.getInstance();
		c.setTime(parse(date, format));
		long t1 = c.getTime().getTime();
		return (int) (t / 1000 - t1 / 1000) / 3600 / 24;
	}

	public static List<Date> parseDateByHours(Date date) {
		Date start = dayStartDate(date);// 转换为天的起始date
		Date nextDayDate = nextDay(start);// 下一天的date

		List<Date> result = new ArrayList<Date>();
		while (start.compareTo(nextDayDate) < 0) {
			result.add(start);
			// 日期加60分钟
			start = addSixthMin(start, 60);
		}

		return result;
	}

	public static List<String> parseDateByHours(Date startDate, Date endDate, int speed) {
		LinkedList<String> list = new LinkedList<>();
		while (list.size() < 11 && startDate.compareTo(endDate) <= 0) {
			list.addFirst(format(endDate, "yyyy-MM-dd HH:00:00"));
			endDate = addSixthMin(endDate, -speed * 60);
		}
		return list;
	}

	public static List<String> parseDateByMinutes(Date startDate, Date endDate, int speed) {
		LinkedList<String> list = new LinkedList<>();
		while (list.size() < 11 && startDate.compareTo(endDate) <= 0) {
			list.addFirst(format(endDate, "yyyy-MM-dd HH:mm:00"));
			endDate = addSixthMin(endDate, -speed);
		}
		return list;
	}

	public static List<String> parseDateBySec(Date startDate, Date endDate, int speed) {
		LinkedList<String> list = new LinkedList<>();
		while (list.size() < 11 && startDate.compareTo(endDate) <= 0) {
			list.addFirst(format(endDate, "yyyy-MM-dd HH:mm:ss"));
			endDate = addSec(endDate, -speed);
		}
		return list;
	}

	/**
	 * 按日解析日期
	 * 
	 * @param startDate
	 *            开始时间
	 * @param endDate
	 *            结束时间
	 * @return
	 */
	public static List<String> parseDateByDay(Date startDate, Date endDate, int speed) {
		Date start = dayStartDate(startDate);// 转换为月的起始date
		Date end = dayStartDate(endDate);// 转换为月的结束date
		List<String> result = new ArrayList<>();
		while (start.compareTo(end) <= 0) {
			result.add(format(start, "yyyy-MM-dd 00:00:00"));
			start = addDay(start, speed);
		}

		return result;
	}

	/**
	 * 按月解析日期
	 * 
	 * @param startDate
	 *            开始时间
	 * @param endDate
	 *            结束时间
	 * @return
	 */
	public static List<String> parseDateByMonth(Date startDate, Date endDate) {
		Date start = monthStartDate(startDate);// 转换为月的起始date
		Date end = monthStartDate(endDate);// 转换为月的结束date
		List<String> result = new ArrayList<>();
		while (start.compareTo(end) <= 0) {
			result.add(format(start, "yyyy-MM"));
			// 加一个月
			start = addOneMonth(start, 1);
		}

		return result;
	}

	/**
	 * 获得本周一0点时间
	 *
	 * @author Jason Yang
	 * @datetime 2017年2月27日 下午3:50:57
	 * @return
	 */
	public static Date getThisWeekMonday() {
		Calendar cal = Calendar.getInstance();
		cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
		cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
		return cal.getTime();
	}

	/**
	 * 获得本周日24点时间
	 *
	 * @author Jason Yang
	 * @datetime 2017年2月27日 下午3:51:03
	 * @return
	 */
	public static Date getThisWeekSunday() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(getThisWeekMonday());
		cal.add(Calendar.DAY_OF_WEEK, 7);
		cal.add(Calendar.SECOND, -1);
		return cal.getTime();
	}

	/**
	 * 获得上上周日0点时间
	 *
	 * @author Jason Yang
	 * @datetime 2017年2月27日 下午3:50:57
	 * @return
	 */
	public static Date getLast2WeekSundayStart() {
		Calendar cal = Calendar.getInstance();
		cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
		cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
		cal.set(Calendar.MILLISECOND, 0);
		cal.add(Calendar.DAY_OF_WEEK, -8);
		return cal.getTime();
	}

	/**
	 * 获得上周六23点59分59秒时间
	 *
	 * @author Jason Yang
	 * @datetime 2017年2月27日 下午3:51:03
	 * @return
	 */
	public static Date getLastWeekSaturdayEnd() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(getLast2WeekSundayStart());
		cal.add(Calendar.DAY_OF_WEEK, 7);
		cal.set(Calendar.MILLISECOND, 0);
		cal.add(Calendar.SECOND, -1);
		return cal.getTime();
	}

	/**
	 * 获得上个月第一天0点时间
	 *
	 * @author Jason Yang
	 * @datetime 2017年2月27日 下午3:51:09
	 * @return
	 */
	public static Date getLastMonthFirst() {
		Calendar cal = Calendar.getInstance();
		cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
		cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
		cal.set(Calendar.MILLISECOND, 0);
		cal.add(Calendar.MONTH, -1);
		return cal.getTime();
	}

	/**
	 * 获得上个月最后一天23点59分59秒时间
	 *
	 * @author Jason Yang
	 * @datetime 2017年2月27日 下午3:51:15
	 * @return
	 */
	public static Date getLastMonthLast() {
		Calendar cal = Calendar.getInstance();
		cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
		cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
		cal.set(Calendar.HOUR_OF_DAY, 24);
		cal.set(Calendar.MILLISECOND, 0);
		cal.set(Calendar.SECOND, -1);
		cal.add(Calendar.MONTH, -1);
		return cal.getTime();
	}

	private static Date addSec(Date start, int offset) {
		Calendar c = Calendar.getInstance();
		c.setTime(start);
		c.add(Calendar.SECOND, offset);
		return c.getTime();
	}

	private static Date addSixthMin(Date start, int offset) {
		Calendar c = Calendar.getInstance();
		c.setTime(start);
		c.add(Calendar.MINUTE, offset);
		return c.getTime();
	}

	private static Date addOneMonth(Date start, int offset) {
		Calendar c = Calendar.getInstance();
		c.setTime(start);
		c.add(Calendar.MONTH, offset);
		return c.getTime();
	}

	private static Date nextDay(Date start) {
		Calendar c = Calendar.getInstance();
		c.setTime(start);
		c.add(Calendar.DATE, 1);
		c.add(Calendar.MINUTE, 60);
		return c.getTime();
	}

	private static Date dayStartDate(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);
		return c.getTime();
	}

	private static Date monthStartDate(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.DAY_OF_MONTH, 1);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);
		return c.getTime();
	}

	public static List<String> split24Time(Date d1, Date d2) {
		LinkedList<String> list = new LinkedList<>();
		while (list.size() < 9 && d1.compareTo(d2) <= 0) {
			list.addLast(format(d1, "yyyy-MM-dd HH:mm:ss"));
			d1 = addSixthMin(d1, 3 * 60);
		}
		return list;
	}

	public static List<String> splitTime(Date d1, Date d2) {
		LinkedList<String> list = new LinkedList<>();
		long diff = d2.getTime() - d1.getTime();
		long a = diff / 10;
		long b = d1.getTime();
		list.addLast(format(d1));

		for (int i = 0; i < 10; i++) {
			b += a;
			list.addLast(format(new Date(b)));
		}
		return list;
	}

	public static List<Date> splitTimeV3(Date d1, Date d2) {
		LinkedList<Date> list = new LinkedList<>();
		long diff = d2.getTime() - d1.getTime();
		long a = diff / 10;
		long b = d1.getTime();
		list.addLast(new Date(b));
		for (int i = 0; i < 10; i++) {
			b += a;
			list.addLast(new Date(b));
		}
		return list;
	}

	// 获得当天0点时间
	public static Date getTimesmorning() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();

	}

	// 获得昨天0点时间
	public static Date getYesterdaymorning() {
		Calendar cal = Calendar.getInstance();
		cal.setTimeInMillis(getTimesmorning().getTime() - 3600 * 24 * 1000);
		return cal.getTime();
	}

	// 获得当天近7天时间
	public static Date getWeekFromNow() {
		Calendar cal = Calendar.getInstance();
		cal.setTimeInMillis(getTimesmorning().getTime() - 3600 * 24 * 1000 * 7);
		return cal.getTime();
	}

	// 获得当天24点时间
	public static Date getTimesnight() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.HOUR_OF_DAY, 24);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();
	}

	// 获得本周一0点时间
	public static Date getTimesWeekmorning() {
		Calendar cal = Calendar.getInstance();
		cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
		cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
		return cal.getTime();
	}

	// 获得本周日24点时间
	public static Date getTimesWeeknight() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(getTimesWeekmorning());
		cal.add(Calendar.DAY_OF_WEEK, 7);
		return cal.getTime();
	}

	// 获得本月第一天0点时间
	public static Date getTimesMonthmorning() {
		Calendar cal = Calendar.getInstance();
		cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
		cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
		return cal.getTime();
	}

	// 获得本月最后一天24点时间
	public static Date getTimesMonthnight() {
		Calendar cal = Calendar.getInstance();
		cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
		cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
		cal.set(Calendar.HOUR_OF_DAY, 24);
		return cal.getTime();
	}

	/**
	 * 当前季度的开始时间，即2012-03-01 00:00:00
	 * 
	 * @return
	 */
	public static Date getCurrentQuarterStartTime() {
		Calendar c = Calendar.getInstance();
		int currentMonth = c.get(Calendar.MONTH) + 1;
		SimpleDateFormat longSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		SimpleDateFormat shortSdf = new SimpleDateFormat("yyyy-MM-dd");
		Date now = null;
		try {
			if (currentMonth >= 1 && currentMonth <= 3)
				c.set(Calendar.MONTH, 0);
			else if (currentMonth >= 4 && currentMonth <= 6)
				c.set(Calendar.MONTH, 3);
			else if (currentMonth >= 7 && currentMonth <= 9)
				c.set(Calendar.MONTH, 4);
			else if (currentMonth >= 10 && currentMonth <= 12)
				c.set(Calendar.MONTH, 9);
			c.set(Calendar.DATE, 1);
			now = longSdf.parse(shortSdf.format(c.getTime()) + " 00:00:00");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return now;
	}

	/**
	 * 当前季度的结束时间，即2012-03-31 23:59:59
	 * 
	 * @return
	 */
	public static Date getCurrentQuarterEndTime() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(getCurrentQuarterStartTime());
		cal.add(Calendar.MONTH, 3);
		return cal.getTime();
	}

	/**
	 * 当年的开始时间，即2012-01-01 00:00:00
	 * 
	 * @return
	 */
	public static Date getCurrentYearStartTime() {
		Calendar cal = Calendar.getInstance();
		cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
		cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.YEAR));
		return cal.getTime();
	}

	/**
	 * 当年的结束时间，即2012-12-31 23:59:59
	 * 
	 * @return
	 */
	public static Date getCurrentYearEndTime() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(getCurrentYearStartTime());
		cal.add(Calendar.YEAR, 1);
		return cal.getTime();
	}

	public static void main(String[] args) throws ParseException {
		// 上上周日开始时间
		Date begin = DateKit.getLast2WeekSundayStart();
		System.out.println(begin.getTime());

		Date d2 = parse("2017-07-16 00:00:00");
		System.out.println(d2.getTime());

	}

}